import { defineStore } from 'pinia';

import type { NotificationItem, UserInfo } from '@/types/interface';
import { createSocketd } from '@/utils/sd';
import { SocketD } from '@noear/socket.d';
import { Client } from '@noear/socket.d/transport/client/Client';
import type { ClientConnector } from "@noear/socket.d/transport/client/ClientConnector";
import { useUserStore } from '@/store';
import { ClientSession } from '@noear/socket.d/transport/client/ClientSession';
import { Listener } from '@noear/socket.d/transport/core/Listener';
import { Session } from '@noear/socket.d/transport/core/Session';
import { Message } from '@noear/socket.d/transport/core/Message';
import { RequestStream } from '@noear/socket.d/transport/stream/Stream';
import { Reply } from '@noear/socket.d/transport/core/Entity';
import { Notice, PageNoticeReq, PageNoticeRes, UserNoticePageReq } from '@/api/system/notice/types';
import { Result } from '@/types/axios';
import { PageResponse } from '@/api/types';
import { ResultEnum } from '@/enums/httpEnum';
let sysNoticeSession:ClientSession=undefined;
let sysNoticeClient:Client=undefined;
const eventListener:Listener = await SocketD.newEventListener().doOnMessage((s,m)=>{
  //监听所有消息（可能不需要）
}).doOn("/push", (s,m)=>{
   //监听来自服务端推送的一条新消息
   pushEvent(s,m);
});

/**
 * push事件
 * 监听来自服务端推送的新消息
 * @param session
 * @param message
 */
const pushEvent=(session:Session,message:Message) =>{
  console.log('监听来自服务端推送的新消息',message)
  let res:Result<Notice>=JSON.parse(message.dataAsString());
  console.log('监听来自服务端推送的新消息',res)
  if(ResultEnum.SUCCESS===res.code && res.result){
    const {setMsgDataNotice,addMsgData,msgData}=useNotificationStore();
    let index=msgData.records.findIndex(item=>item.id==res.result.id);
    if(index>-1){
      setMsgDataNotice(res.result,index)
    }else{
      addMsgData(res.result)
    }
  }
}

export const useNotificationStore = defineStore('notification', {
  state: () => ({
    msgData:PageResponse<Array<PageNoticeRes>>,
  }),
  getters: {
    getMsgData: (state) => state.msgData,
  },
  actions: {
    setMsgDataNotice(data:Notice,index:number){
        // Object.assign(data,this.msgData.records[index]);
        Object.assign(this.msgData.records[index],data);
    },
    addMsgData(data:Notice){
      // Object.assign(data,this.msgData.records[index]);
      this.msgData.records.unshift(data);
      ++this.msgData.totalRow
    },
    /**
     * 将数据插入pina通知数据集
     * @param data 需要插入的数据
     * @param refresh 是否重置数据集
     */
    setMsgDataPageNoticeRes(data:PageResponse<Array<PageNoticeRes>>,refresh:boolean){
      if(refresh){
        this.msgData=data
      }else{
        data.records.forEach(item=>{
          this.msgData.records.push(item);
        })
        this.msgData.totalRow=data.totalRow
        this.msgData.pageNumber=data.pageNumber
        this.msgData.pageSize=data.pageSize
      }

    },
    /**
     * 初始化系统通知连接
     * @param params 分页参数
     */
    async initysNoticeSocketd(params:UserNoticePageReq){
      const userInfo:UserInfo=await useUserStore().getUserInfo();
      sysNoticeClient=(await createSocketd(import.meta.env.VITE_SD_SYS_NOTICE))
      .listen(eventListener)
      .config(c => c.metaPut("token",userInfo.token).metaPut("Language",userInfo.language))
      .connectHandler(c => {
        //每次连接时，可修改元信息
        c.getConfig().metaPut("Language",userInfo.language);
        return c.connect();
      });
      sysNoticeSession = await sysNoticeClient.open();
      let reply:Reply=await this.pageNotice(params);
      let res:Result<PageResponse<Array<PageNoticeRes>>>=JSON.parse(reply.dataAsString());
      if(ResultEnum.SUCCESS===res.code){
        this.msgData=res.result
      }
    },
    /**
     * 获取系统通知
     * @param params 分页参数
     * @returns
     */
    pageNotice(params:UserNoticePageReq):Promise<Reply>{
      // 默认10秒超时
      return new Promise((resolve, reject) => {
        try{
          sysNoticeSession.sendAndRequest("/get", SocketD.newEntity(JSON.stringify(params)))
          .thenReply(reply=>resolve(reply))
          .thenError(err => reject(err))
        }catch (err){
          reject(err)
        }
      });
    },
    /**
     * 读通知
     * @param params 分页参数
     * @returns
     */
    async read(params:Array<string>):Promise<boolean>{
      //10秒超时
      let reply:Reply= await sysNoticeSession.sendAndRequest("/read", SocketD.newEntity(JSON.stringify(params)), 10_000).await();
      let res:Result<Array<string>>=JSON.parse(reply.dataAsString());
      console.log('read reply',res);
      if(ResultEnum.SUCCESS === res.code){
        this.msgData.records=this.msgData.records.filter((item:PageNoticeRes) => !(res.result.indexOf(item.id) > -1))
        --this.msgData.totalRow
        return true;
      }
      return false;
    },
    async readRef(noticeId:Array<string>,params:UserNoticePageReq):Promise<boolean>{
      //10秒超时
      let reply:Reply= await sysNoticeSession.sendAndRequest("/read", SocketD.newEntity(JSON.stringify(noticeId)), 10_000).await();
      let res:Result<Array<string>>=JSON.parse(reply.dataAsString());
      console.log('read reply',res);
      if(ResultEnum.SUCCESS === res.code){
        let reply:Reply=await this.pageNotice(params);
        let res:Result<PageResponse<Array<PageNoticeRes>>>=JSON.parse(reply.dataAsString());
        if(ResultEnum.SUCCESS===res.code){
          this.msgData=res.result
        }
        return true;
      }
      return false;
    },
    /**
     * 取消读通知
     * @param params
     * @returns
     */
    async unreadRef(noticeId:Array<string>,params:UserNoticePageReq):Promise<boolean>{
      //10秒超时
      let reply:Reply= await sysNoticeSession.sendAndRequest("/unread", SocketD.newEntity(JSON.stringify(noticeId)), 10_000).await();
      console.log('read reply',reply.dataAsString());
      let res:Result<any>=JSON.parse(reply.dataAsString());
      console.log('read reply',res);
      if(ResultEnum.SUCCESS === res.code){
        let reply:Reply=await this.pageNotice(params);
        let res:Result<PageResponse<Array<PageNoticeRes>>>=JSON.parse(reply.dataAsString());
        if(ResultEnum.SUCCESS===res.code){
          this.msgData=res.result
        }
        return true;
      }
      return false;
    },
  },
});
